from libs._types import *

class SymbolTable:
    def __init__(self) -> None:
        self.table = {}
    
    def add(self, name, value):
        self.table[name] = value
    
    def remove(self, name):
        self.table.pop(name)

class Execute:
    def __init__(self) -> None:
        self.symbol_table = SymbolTable()

    def execute_unit(self, unit):
        if unit.unit_type == "assignment":
            self.symbol_table.add(unit.left_value.value, self.execute_unit(unit.right_value))
            return TypeNull()
        elif unit.unit_type == "add":
            return self.execute_unit(unit.left_value).add(self.execute_unit(unit.right_value))
        elif unit.unit_type == "sub":
            return self.execute_unit(unit.left_value).sub(self.execute_unit(unit.right_value))
        elif unit.unit_type == "mul":
            return self.execute_unit(unit.left_value).mul(self.execute_unit(unit.right_value))
        elif unit.unit_type == "div":
            return self.execute_unit(unit.left_value).div(self.execute_unit(unit.right_value))
        elif unit.unit_type == "constant":
            if unit._type.value == 9: #int
                return TypeInt(unit.value)
            elif unit._type.value == 10: #float
                return TypeFloat(unit.value)
            elif unit._type.value == 11: #symbol
                assert unit.value in self.symbol_table.table.keys(), "Unknown variable "+unit.value
                return self.symbol_table.table[unit.value]

    def execute(self, tree: list):
        for unit in tree:
            self.execute_unit(unit)
        return TypeNull()